//! Upravljanje prekidima - razina jezgre

#define _J_POZIVI_JEZGRE_C_
#include "pozivi_jezgre.h"

#include "tipovi.h"
#include "razno.h"
#include "spremnik.h"
#include "ispis.h"
#include <arh/kontekst.h>

//poziva se iz prekidne funkcije
void j_pozivi_jezgre(int id_prekida, void *kontekst)
{
	int povvr;
	struct { //parametri su na stogu dretve u ovom redoslijedu
		int id;
		void *param;
		int *povvr;
	} *param;

	param = j_puj(arh_dohvati_vrh_stoga_dretve(kontekst));

	if (param->id < 0 || param->id > BROJ_J_FUNKCIJA) {
		j_ispisi("id van granica (%d)", param->id);
	}
	else {
		//ako naknadno treba mijenjati povratnu vrijednost
		//zapisi adresu u opisnik dretve (npr. za cekaj_sinkro_t func)
		j_zapisi_adresu_povratne_vrijednosti(j_puj(param->povvr));

		povvr = (j_fun[param->id])(j_puj(param->param));
		
		//nema povratka iz:
		//	DRETVA_ZAVRSETAK, KRAJ_OBRADE_DOGADJAJA
		//pa ne stavljati povratnu vrijednost 'negdje'
		if (param->id != DRETVA_ZAVRSETAK && 
			param->id != KRAJ_OBRADE_DOGADJAJA)
			
			*((int *) j_puj(param->povvr)) = povvr;
	}
}


//implementacije - par primjera

int funkcija1 (void *x)
{
	//povecava vrijednost za 1 (pretpostavlja int *)
	int *p = x;
	
	PARAMNULL(p);
	
	*p += 1;

	return 7;
}

int funkcija2 (void *x)
{
	//racuna duljinu teksta (pretpostavlja char *)
	int i;
	char *c = x;
	
	PARAMNULL(c);

	for (i = 0; c[i] != 0; i++)
		;

	return i + 1;
}

int funkcija3 (void *x)
{
	//trazi najmanji broj (pretpostavlja pointer na {int, double[]})
	int *np = x;
	double *p;
	int n, i, min = -1;
	
	PARAMNULL(np);

	n = *np;
	np++;
	p = (double *) np;

	if (n > 0) {
		min = 0;

		for (i = 1; i < n; i++)
			if (p[i] < p[min])
				min = i;
	}
	
	return min;
}
